﻿using System;
using System.Collections.Generic;
using FileHelpers;

namespace SecurityModule.Parsers.Format2014
{
    /// <summary>
    /// Parses tax files provided by IDOR as of 2014, this format is no longer supported by IDOR as of Jan, 2015. This class uses <see cref="FileHelperEngine{T}"/> to parse the CSV file.
    /// </summary>
    public class TaxParser : IParser
    {
        /// <summary>
        /// Returns true if the file correponds with IDOR tax format as of 2014.
        /// </summary>
        /// <param name="data">Data to be processed as plain text.</param>
        /// <returns>True if the parser can process file, false otherwise.</returns>
        /// <exception cref="FileFormatException">Thrown when the file can't be processed structurally by <see cref="FileHelperEngine{T}"/>.</exception>
        /// /// <exception cref="FileFormatException">Thrown when the file can't be processed structurally by <see cref="FileHelperEngine{T}"/>.</exception>
        public bool CanParse(string data)
        {
            try
            {
                var lines = data.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);

                var taxTypeLine = lines[2];
                if (taxTypeLine == null)
                    throw new FileFormatException();
                var taxtypeLineSplitted = taxTypeLine.Split(new[] { "," }, StringSplitOptions.None);
                if (taxtypeLineSplitted.Length < 1)
                    throw new FileFormatException();

                var header = lines[3];
                if (header == null)
                    throw new FileFormatException();
                var headerSplitted = header.Split(new[] { "," }, StringSplitOptions.None);
                if (headerSplitted.Length < 6)
                    throw new FileFormatException();

                var firstPeriod = headerSplitted[2].Replace("\"", "").Trim().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                if (firstPeriod.Length < 2)
                    throw new FileFormatException();
                switch (firstPeriod[0])
                {
                    case "JAN":
                    case "MAY":
                    case "SEP":
                        break;
                    default:
                        throw new FileFormatException();
                }
                // ReSharper disable ReturnValueOfPureMethodIsNotUsed
                int.Parse(firstPeriod[1]);
                // ReSharper restore ReturnValueOfPureMethodIsNotUsed
                new FileHelperEngine<TaxLine>().ReadString(lines[4]);
            }
            catch (Exception)
            {

                return false;
            }
            return true;
        }

        /// <summary>
        /// Parses the provided data and returns a list of <see cref="ParseResultItem"/>.
        /// </summary>
        /// <param name="data">Data to be processed as plain text.</param>
        /// <returns>A list of <see cref="ParseResultItem"/> each with ResultKind set to <see cref="ResultKind.Tax"/> and TaxItems containing 4 items (1 for each month), AccountNum and Site must have values and the address-related data will be all null.</returns>
        /// <exception cref="FileHelpersException">Thrown when the provided data can't be parsed using this parser.</exception>
        public List<ParseResultItem> Parse(string data)
        {
            var lines = data.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
            // lines[0]: Municipality Name
            // lines[1]: To be ignored according to Scott

            var taxTypeLine = lines[2];
            if (taxTypeLine == null)
                throw new FileFormatException();
            var taxtypeLineSplitted = taxTypeLine.Split(new[] { "," }, StringSplitOptions.None);
            if (taxtypeLineSplitted.Length < 1)
                throw new FileFormatException();
            var taxType = taxtypeLineSplitted[0].Replace("\"", "");

            var header = lines[3];
            if (header == null)
                throw new FileFormatException();
            var headerSplitted = header.Split(new[] { "," }, StringSplitOptions.None);
            if (headerSplitted.Length < 6)
                throw new FileFormatException();

            var firstPeriod = headerSplitted[2].Replace("\"", "").Trim().Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
            if (firstPeriod.Length < 2)
                throw new FileFormatException();
            int firstMonth;
            switch (firstPeriod[0].ToUpper())
            {
                case "JAN":
                    firstMonth = 1;
                    break;
                case "MAY":
                    firstMonth = 5;
                    break;
                case "SEP":
                    firstMonth = 9;
                    break;
                default:
                    throw new FileFormatException();
            }

            int year;
            try
            {
                year = int.Parse(firstPeriod[1]);
            }
            catch (Exception ex)
            {
                throw new FileFormatException("Wrong number format for year", ex);
            }
            var e = new FileHelperEngine<TaxLine>();
            var result = new List<ParseResultItem>();
            for (var i = 4; i < lines.Length - 1; i++)
            {
                if (string.IsNullOrEmpty(lines[i])) continue;
                var taxLine = e.ReadString(lines[i])[0];
                if (taxLine.AccountNumber < 0) continue;
                result.Add(new ParseResultItem
                    {
                        AccountNum = taxLine.AccountNumber,
                        Site = taxLine.Site,
                        TaxItems = new[]
                            {
                                new ParseTaxResultItem
                                    {
                                        TaxType = taxType,
                                        Month = firstMonth,
                                        Year = year,
                                        Value = taxLine.Val1
                                    },
                                new ParseTaxResultItem
                                    {
                                        TaxType = taxType,
                                        Month = firstMonth + 1,
                                        Year = year,
                                        Value = taxLine.Val2
                                    },
                                new ParseTaxResultItem
                                    {
                                        TaxType = taxType,
                                        Month = firstMonth + 2,
                                        Year = year,
                                        Value = taxLine.Val3
                                    },
                                new ParseTaxResultItem
                                    {
                                        TaxType = taxType,
                                        Month = firstMonth + 3,
                                        Year = year,
                                        Value = taxLine.Val4
                                    }
                            },
                        ResultKind = ResultKind.Tax
                    });
            }

            return result;
        }
    }
}
